
#include <btPointConstraint.h>

#include <BLabel>
#include <BGridLayout>
#include <BVBoxLayout>
#include <BHBoxLayout>
#include <BGroupBox>

#include "StringUtils.h"
#include "ConearConstraintPanel.h"

ConearConstraintPanel::ConearConstraintPanel(BWidget* parent) : BWidget(parent)
{
	this->setTitle(BConearConstraint::TypeName());

	_bodyAGroupBox = new BGroupBox();
	{
		_positionAEdit = new BLineEdit();
		_rotateAEdit = new BLineEdit();
		BGridLayout* gridLayout = new BGridLayout(_bodyAGroupBox);
		gridLayout->setWidget(0, 0, new BLabel("position"));
		gridLayout->setWidget(0, 1, _positionAEdit);
		gridLayout->setWidget(1, 0, new BLabel("rotate"));
		gridLayout->setWidget(1, 1, _rotateAEdit);
	}

	_bodyBGroupBox = new BGroupBox();
	{
		_positionBEdit = new BLineEdit();
		_rotateBEdit = new BLineEdit();
		BGridLayout* gridLayout = new BGridLayout(_bodyBGroupBox);
		gridLayout->setWidget(0, 0, new BLabel("position"));
		gridLayout->setWidget(0, 1, _positionBEdit);
		gridLayout->setWidget(1, 0, new BLabel("rotate"));
		gridLayout->setWidget(1, 1, _rotateBEdit);
	}

	BGroupBox* linearLimitGroupBox = new BGroupBox("Linear Limit");
	{
		BLabel* minimumLabel = new BLabel("minimum");
		_linearMinSpinBox = new BRealSpinBox();

		BLabel* maximumLabel = new BLabel("maximum");
		_linearMaxSpinBox = new BRealSpinBox();

		BGridLayout* gridLayout = new BGridLayout(linearLimitGroupBox);
		gridLayout->setWidget(1, 0, minimumLabel);
		gridLayout->setWidget(1, 1, _linearMinSpinBox);
		gridLayout->setWidget(2, 0, maximumLabel);
		gridLayout->setWidget(2, 1, _linearMaxSpinBox);
	}

	BGroupBox* angularLimitGroupBox = new BGroupBox("Angular Limit");
	{
		BLabel* twistSpanLabel = new BLabel("Twist Span");
		_twistSpanSpinBox = new BRealSpinBox();

		BLabel* swingSpanLabel = new BLabel("Swing Span");
		BHBoxLayout* swingSpanLayout = new BHBoxLayout();
		{
			_swingSpan1SpinBox = new BRealSpinBox();
			_swingSpan2SpinBox = new BRealSpinBox();
			swingSpanLayout->addWidget(_swingSpan1SpinBox);
			swingSpanLayout->addWidget(_swingSpan2SpinBox);
		}

		BLabel* softnessLabel = new BLabel("Softness");
		_softnessSpinBox = new BRealSpinBox();

		BLabel* biasFactorLabel = new BLabel("Bias Factor");
		_biasFactorSpinBox = new BRealSpinBox();

		BLabel* relaxFactorLabel = new BLabel("Relax Factor");
		_relaxFactorSpinBox = new BRealSpinBox();

		BLabel* minimumLabel = new BLabel("minimum");
		_angularMinSpinBox = new BRealSpinBox();

		BLabel* maximumLabel = new BLabel("maximum");
		_angularMaxSpinBox = new BRealSpinBox();

		BGridLayout* gridLayout = new BGridLayout(angularLimitGroupBox);
		gridLayout->setWidget(0, 0, twistSpanLabel);
		gridLayout->setWidget(0, 1, _twistSpanSpinBox);
		gridLayout->setWidget(1, 0, swingSpanLabel);
		gridLayout->setLayout(1, 1, swingSpanLayout);
		gridLayout->setWidget(2, 0, softnessLabel);
		gridLayout->setWidget(2, 1, _softnessSpinBox);
		gridLayout->setWidget(3, 0, biasFactorLabel);
		gridLayout->setWidget(3, 1, _biasFactorSpinBox);
		gridLayout->setWidget(4, 0, relaxFactorLabel);
		gridLayout->setWidget(4, 1, _relaxFactorSpinBox);
		gridLayout->setWidget(5, 0, minimumLabel);
		gridLayout->setWidget(5, 1, _angularMinSpinBox);
		gridLayout->setWidget(6, 0, maximumLabel);
		gridLayout->setWidget(6, 1, _angularMaxSpinBox);
	}

	_motorGroupBox = new BGroupBox("Motor");
	_motorGroupBox->setCheckable(true);
	_motorGroupBox->setChecked(true);
	{
		BLabel* targetVelocityLabel = new BLabel("Target Velocity");
		_targetVelocitySpinBox = new BRealSpinBox();

		BLabel* maxImpulseLabel = new BLabel("Max Impulse");
		_maxImpulseSpinBox = new BRealSpinBox();

		BGridLayout* gridLayout = new BGridLayout(_motorGroupBox);
		gridLayout->setWidget(2, 0, targetVelocityLabel);
		gridLayout->setWidget(2, 1, _targetVelocitySpinBox);
		gridLayout->setWidget(3, 0, maxImpulseLabel);
		gridLayout->setWidget(3, 1, _maxImpulseSpinBox);
	}

	BVBoxLayout* vlayout = new BVBoxLayout(this);
	vlayout->addWidget(_bodyAGroupBox);
	vlayout->addWidget(_bodyBGroupBox);
	vlayout->addWidget(linearLimitGroupBox);
	vlayout->addWidget(angularLimitGroupBox);
	vlayout->addWidget(_motorGroupBox);

	connect(this, Signal_AssetChanged, &ConearConstraintPanel::slotAssetChanged);

	connect(_positionAEdit, Signal_EditFinished, &ConearConstraintPanel::slotPositionAEditFinished);
	connect(_rotateAEdit, Signal_EditFinished, &ConearConstraintPanel::slotRotateAEditFinished);
	connect(_positionBEdit, Signal_EditFinished, &ConearConstraintPanel::slotPositionBEditFinished);
	connect(_rotateBEdit, Signal_EditFinished, &ConearConstraintPanel::slotRotateBEditFinished);

	connect(_twistSpanSpinBox, Signal_EditFinished, &ConearConstraintPanel::slotTwistSpanEditFinished);
	connect(_swingSpan1SpinBox, Signal_EditFinished, &ConearConstraintPanel::slotSwingSpanEditFinished);
	connect(_swingSpan2SpinBox, Signal_EditFinished, &ConearConstraintPanel::slotSwingSpanEditFinished);
	connect(_softnessSpinBox, Signal_EditFinished, &ConearConstraintPanel::slotSoftnessEditFinished);
	connect(_biasFactorSpinBox, Signal_EditFinished, &ConearConstraintPanel::slotLimitBiasEditFinsihed);
	connect(_relaxFactorSpinBox, Signal_EditFinished, &ConearConstraintPanel::slotLimitRelaxFactorEditFinihsed);
	connect(_linearMinSpinBox, Signal_EditFinished, &ConearConstraintPanel::slotLinearLimitEditFinished);
	connect(_linearMaxSpinBox, Signal_EditFinished, &ConearConstraintPanel::slotLinearLimitEditFinished);
	connect(_angularMinSpinBox, Signal_EditFinished, &ConearConstraintPanel::slotAngularLimitEditFinished);
	connect(_angularMaxSpinBox, Signal_EditFinished, &ConearConstraintPanel::slotAngularLimitEditFinished);
	connect(_motorGroupBox, Signal_Toggled, &ConearConstraintPanel::slotMotorEnabledToggled);
	connect(_targetVelocitySpinBox, Signal_EditFinished, &ConearConstraintPanel::slotTargetVelocityEditFinished);
	connect(_maxImpulseSpinBox, Signal_EditFinished, &ConearConstraintPanel::slotMaxImpulseEditFinished);
}
ConearConstraintPanel::~ConearConstraintPanel()
{

}

void ConearConstraintPanel::slotAssetChanged(BObject* object, const BValue& value)
{
	_conearConstraint = value;
	if (_conearConstraint)
	{
		if (_conearConstraint->nodeA())
		{
			const BVector& pointA = _conearConstraint->pointA();
			_bodyAGroupBox->setTitle(_conearConstraint->nodeA()->name());
			_positionAEdit->setText(StringFromVector(pointA));
			//_rotateAEdit->setText(StringFromQuater(matrixA.rotate()));
		}
		if (_conearConstraint->nodeB())
		{
			const BVector& pointB = _conearConstraint->pointB();
			_bodyBGroupBox->setTitle(_conearConstraint->nodeB()->name());
			_positionBEdit->setText(StringFromVector(pointB));
			//_rotateBEdit->setText(StringFromQuater(matrixB.rotate()));
		}
		BReal twistSpan = _conearConstraint->twistSpan();
		_twistSpanSpinBox->setValue(twistSpan);
		BReal swingSpan1 = _conearConstraint->swingSpan1();
		_swingSpan1SpinBox->setValue(swingSpan1);
		BReal swingSpan2 = _conearConstraint->swingSpan2();
		_swingSpan2SpinBox->setValue(swingSpan2);
		BReal softness = _conearConstraint->softness();
		_softnessSpinBox->setValue(softness);
		BReal biasFactor = _conearConstraint->biasFactor();
		_biasFactorSpinBox->setValue(biasFactor);
		BReal relaxFactor = _conearConstraint->relaxFactor();
		_relaxFactorSpinBox->setValue(relaxFactor);
	}
}

void ConearConstraintPanel::slotPositionAEditFinished(BObject* object, const BValue& value)
{
	const BString& text = value;
	const BVector& pointA = StringToVector(text);
	_conearConstraint->setPointA(pointA);
}
void ConearConstraintPanel::slotRotateAEditFinished(BObject* object, const BValue& value)
{
	const BString& text = value;
	const BQuater& rotate = StringToQuater(text);
	//BMatrix matrixA = _conearConstraint->matrixA();
	//matrixA.setRotate(rotate);
	//_conearConstraint->setMatrixA(matrixA);
}
void ConearConstraintPanel::slotPositionBEditFinished(BObject* object, const BValue& value)
{
	const BString& text = value;
	const BVector& pointB = StringToVector(text);
	_conearConstraint->setPointB(pointB);
}
void ConearConstraintPanel::slotRotateBEditFinished(BObject* object, const BValue& value)
{
	const BString& text = value;
	const BQuater& rotate = StringToQuater(text);
	//BMatrix matrixB = _conearConstraint->matrixB();
	//matrixB.setRotate(rotate);
	//_conearConstraint->setMatrixB(matrixB);
}

void ConearConstraintPanel::slotTwistSpanEditFinished(BObject* object, const BValue& value)
{
	BReal twistSpan = value;
	_conearConstraint->setTwistSpan(twistSpan);
}
void ConearConstraintPanel::slotSwingSpanEditFinished(BObject* object, const BValue& value)
{
	BReal swingSpan1 = _swingSpan1SpinBox->value();
	BReal swingSpan2 = _swingSpan2SpinBox->value();
	_conearConstraint->setSwingSpan1(swingSpan1);
	_conearConstraint->setSwingSpan2(swingSpan2);
}
void ConearConstraintPanel::slotSoftnessEditFinished(BObject* object, const BValue& value)
{
	BReal softness = value;
	_conearConstraint->setSoftness(softness);
}
void ConearConstraintPanel::slotLimitBiasEditFinsihed(BObject* object, const BValue& value)
{
	BReal biasFactor = value;
	_conearConstraint->setBiasFactor(biasFactor);
}
void ConearConstraintPanel::slotLimitRelaxFactorEditFinihsed(BObject* object, const BValue& value)
{
	BReal relaxFactor = value;
	_conearConstraint->setRelaxFactor(relaxFactor);
}
void ConearConstraintPanel::slotLinearLimitEditFinished(BObject* object, const BValue& value)
{
	BReal min = _linearMinSpinBox->value();
	BReal max = _linearMaxSpinBox->value();
}
void ConearConstraintPanel::slotAngularLimitEditFinished(BObject* object, const BValue& value)
{
	BReal min = _angularMinSpinBox->value();
	BReal max = _angularMaxSpinBox->value();
}
void ConearConstraintPanel::slotMotorEnabledToggled(BObject* object, const BValue& value)
{
	bool motorEnabled = value;

}
void ConearConstraintPanel::slotTargetVelocityEditFinished(BObject* object, const BValue& value)
{
	BReal targetVelocity = value;

}
void ConearConstraintPanel::slotMaxImpulseEditFinished(BObject* object, const BValue& value)
{
	BReal maxImpulse = value;

}
